﻿using Furion.DependencyInjection;
using Furion.DynamicApiController;
using HiSport.Core.Entity;
using Microsoft.AspNetCore.Mvc;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using HiSport.Core.Util;
using Mapster;
using SqlSugar;
using System.ComponentModel;
using HiSport.Core;
using Microsoft.VisualBasic;
using StackExchange.Redis;
using HiSport.Application.HiSportService.Bas.BasVenuesManagement.Dtos;
using HiSport.Core.Entity.HiSportEntity.Bas;
using HiSport.Application.HiSportService.Bas.BasDtos;
using DocumentFormat.OpenXml.Vml;
using Furion.ClayObject.Extensions;
using Elastic.Clients.Elasticsearch.Xpack;
using AngleSharp.Dom;

namespace HiSport.Application.HiSportService.Bas.BasVenuesManagement.Service
{

    /// <summary>
    /// 场馆
    /// </summary>
    //[ApiDescriptionSettings("基础资料", Tag = "场馆", SplitCamelCase = false)]
    [ApiDescriptionSettings("VenueSetup", Tag = "Basvenues", SplitCamelCase = false)]
    public class BasVenuesService : ITransient, IBasVenuesService, IDynamicApiController
    {
        private readonly SqlSugarRepository<BasVenues> _basVenuesRep;
        private readonly SqlSugarRepository<SysOrg> _sysOrgRep;
        private readonly SqlSugarRepository<BasVenuesEventsType> _basVenuesEventsTypeRep;
        private readonly SqlSugarRepository<BasVenuesImage> _basVenuesImageRep;
        private readonly SqlSugarRepository<SysDictType> _sysDictTypeRep;
        private readonly SqlSugarRepository<BasSportsEventsType> _sportEventsTypeRep;
        public readonly ISqlSugarClient _dbContext;

        public BasVenuesService(
            SqlSugarRepository<BasVenues> basVenuesRep,
            SqlSugarRepository<SysOrg> sysOrgRep,
            SqlSugarRepository<SysDictType> sysDictTypeRep,
             SqlSugarRepository<BasVenuesEventsType> basVenuesEventsTypeRep,
             SqlSugarRepository<BasVenuesImage> basVenuesImageRep,
             ISqlSugarClient dbContext,
             SqlSugarRepository<BasSportsEventsType> sportEventsTypeRep
            )
        {
            _basVenuesRep = basVenuesRep;
            _sysOrgRep = sysOrgRep;
            _sysDictTypeRep = sysDictTypeRep;
            _basVenuesEventsTypeRep = basVenuesEventsTypeRep;
            _basVenuesImageRep = basVenuesImageRep;
            _sportEventsTypeRep = sportEventsTypeRep;
            _dbContext= dbContext;
        }


        /// <summary>
        /// 创建场馆
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [UnitOfWork]
        [ApiDescriptionSettings(Name = "Create"), HttpPost]
        [DisplayName("创建场馆")]
        public async Task<long> Create(BasVenuesCreateUpdateInputDto input)
        {
            #region 验证参数
            await CheckParam(input, true);
            #endregion

            #region 场馆主表
            var data = input.Adapt<BasVenues>();
            data.Id = 0;//创建的时候ID必须=0
            data.IsDelete = false;//创建的时候ID必须=0
            var newOrg = await _basVenuesRep.AsInsertable(data).ExecuteReturnEntityAsync();
            var venuesId = newOrg.Id;
            await EditVenuesEventsTypeAndVenuesImage(venuesId, input.EventsTypeList, input.ImageList);
            #endregion

            return venuesId;
        }


        /// <summary>
        /// 修改场馆
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>       
        [ApiDescriptionSettings(Name = "Update")]
        [DisplayName("修改场馆")]
        public async Task Update(BasVenuesCreateUpdateInputDto input)
        {
            #region 验证参数

            await CheckParam(input, false);
            var venuesId = input.Id;
            #endregion

            //更新场馆
            await _basVenuesRep.AsUpdateable(input.Adapt<BasVenues>())
                .IgnoreColumns(true)
                .ExecuteCommandAsync();
            //修改组织
            _basVenuesRep.Context.Updateable<object>()
         .AS("BasVenues")
         .SetColumns("CreateOrgId", input.CreateOrgId)
         .Where($"id={input.Id}").ExecuteCommand();

            await EditVenuesEventsTypeAndVenuesImage(input.Id, input.EventsTypeList, input.ImageList);
        }


        /// <summary>
        /// 查询单个场馆
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns></returns>       
        [ApiDescriptionSettings(Name = "Get")]
        [DisplayName("查询单个场馆")]
        public async Task<BasVenuesBasicDto> Get(long id)
        {
            var data = await GetBasVenues(id);
            var result = data.Adapt<BasVenuesBasicDto>();
            //映射
            await SiteTypeMap(new List<BasVenuesBasicDto> { result }, true, true);
            return result;

        }

        /// <summary>
        /// 查询场地类型列表 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>       
        [ApiDescriptionSettings(Name = "GetListPage"), HttpPost]
        [DisplayName("查询场馆列表")]
        public async Task<SqlSugarPagedList<BasVenuesBasicDto>> GetListPage(BasVenuesInputDto input)
        {
            ParamNull(input);
            var data = SqlWhere(input);
            if (data == null) return new SqlSugarPagedList<BasVenuesBasicDto>();

            //排序 分页
            var result = await data.OrderBuilder(input)
                .Select(x => new BasVenuesBasicDto()
                {
                    Id = x.Id.SelectAll(),
                })
                .ToPagedListAsync(input.Page, input.PageSize);

            //冗余字段赋值
            await SiteTypeMap(result.Items.ToList(), true, true);
            return result;
        }

        /// <summary>
        /// 删除场馆
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [UnitOfWork]
        [ApiDescriptionSettings(Name = "Delete")]
        [DisplayName("删除场馆")]
        public async Task Delete(DeleteInputDto input)
        {
            ParamNull(input);

            //是否存在当前ID的场地类型
            var id = input.Id;
            var data = await GetBasVenues(id);

            //启用的类型不能进行删除
            if (data.Status == 1)
            {
                throw Oops.Oh("启用的场馆不能进行删除");
            }

            //TODO:被引用的场馆不能被删除
            //TODO:删除关联表
            await _basVenuesRep.FakeDeleteAsync(data);
        }

        /// <summary>
        /// 修改状态(启用，停用)
        /// </summary>
        /// <returns></returns>     
        [UnitOfWork]
        [ApiDescriptionSettings(Name = "UpdateStatus")]
        [DisplayName("修改状态(启用，停用)")]
        public async Task UpdateStatus(UpdateStatusinputDto input)
        {
            ParamNull(input);

            var status = input.Status;
            var statusList = new List<short> { 0, 1 };
            if (!statusList.Contains(status))
            {
                throw Oops.Oh($"参数有误:不支持此状态值{status}");
            }

            var id = input.Id;
            var data = await GetBasVenues(id);
            data.Status = input.Status;
            await _basVenuesRep.UpdateAsync(data);

        }

        #region 其余私有方法

        /// <summary>
        /// 查询单个场馆信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private async Task<BasVenues> GetBasVenues(long id)
        {

            var data = await _basVenuesRep.GetFirstAsync(a => a.Id == id && a.IsDelete == false);
            if (data == null) throw Oops.Oh("未查询到当前场馆信息");
            return data;
        }


        /// <summary>
        /// 验证参数
        /// </summary>
        /// <param name="input"></param>
        /// <param name="isCreate"></param>
        /// <returns></returns>
        private async Task CheckParam(BasVenuesCreateUpdateInputDto input, bool isCreate)
        {

            #region 验证参数

            ParamNull(input);

            var venuesName = input.VenuesName;
            if (string.IsNullOrWhiteSpace(venuesName))
            {
                throw Oops.Oh("参数错误:场管名称不能为空");
            }
            var venuesCode = input.VenuesCode;
            if (string.IsNullOrWhiteSpace(venuesCode))
            {
                throw Oops.Oh("参数错误:场管编码不能为空");
            }

            //机构必填
            var orgId = input.CreateOrgId;
            if (orgId <= 0) throw Oops.Oh("参数错误:机构必填");
            var orgData = await _sysOrgRep.GetFirstAsync(a => a.Id == orgId);
            if (orgData == null) throw Oops.Oh("机构不存在");


            //场馆编码：租户内唯一，必填，
            //场馆名称：租户内唯一，必填
            var isSame = false;
            if (isCreate)
            {
                isSame = await _basVenuesRep.IsAnyAsync(a => a.IsDelete == false && (a.VenuesName == venuesName || a.VenuesCode == venuesCode));
            }
            else
            {
                var id = input.Id;

                var data = await GetBasVenues(id);

                isSame = await _basVenuesRep.IsAnyAsync(a => a.IsDelete == false && a.Id != id && (a.VenuesName == venuesName || a.VenuesCode == venuesCode));
            }
            if (isSame) { throw Oops.Oh($"已存在此场馆编码或者场馆名称"); }

            #endregion

        }

        /// <summary>
        /// 查询列表Where条件拼装
        /// 要验证返回NULL的情况
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private ISugarQueryable<BasVenues> SqlWhere(BasVenuesInputDto input)
        {
            ParamNull(input);
            var data = _basVenuesRep.AsQueryable();
            data = data.Where(a => a.IsDelete == false);

            #region 机构
            var orgIds = input.OrgIds;
            if (!orgIds.IsNullOrEmpty() && orgIds.Any())
            {
                data = data.Where(a => orgIds.Contains(a.CreateOrgId.Value));
            }
            #endregion

            #region 场馆编码-模糊查询
            var venuesCode = input.VenuesCode;
            if (!string.IsNullOrWhiteSpace(venuesCode))
            {
                data = data.Where(a => a.VenuesCode.Contains(venuesCode));
            }
            #endregion

            #region 场馆名称-模糊查询
            var venuesName = input.VenuesName;
            if (!string.IsNullOrWhiteSpace(venuesName))
            {
                data = data.Where(a => a.VenuesName.Contains(venuesName));
            }
            #endregion

            #region 运动类型Code
            var sportsEventsTypeCodeList = input.SportsEventsTypeCodeList;
            if (!sportsEventsTypeCodeList.IsNullOrEmpty() && sportsEventsTypeCodeList.Any())
            {

                data = data.Where(a => SqlFunc.Subqueryable<BasVenuesEventsType>().Where(b => b.IsDelete == false && b.VenuesId == a.Id && sportsEventsTypeCodeList.Contains(b.SportsEventsTypeCode)).Any());

            }
            #endregion

            #region 状态
            var status = input.Status;
            if (status != null && status.HasValue && status.Value > 0)
            {
                data = data.Where(a => a.Status == status.Value);
            }
            #endregion

            #region 创建时间

            #region  创建时间-开始时间

            var createTime = input.CreateTimeStart;
            if (createTime != null && createTime.HasValue)
            {
                data = data.Where(a => a.CreateTime >= createTime.Value);
            }

            #endregion

            #region  创建时间-结束时间

            var createTimeEnd = input.CreateTimeEnd;
            if (createTimeEnd != null && createTimeEnd.HasValue)
            {
                data = data.Where(a => a.CreateTime <= createTimeEnd.Value);
            }
            #endregion

            #endregion

            #region 营业状态
            var operatingStatus = input.OperatingStatus;
            if (operatingStatus.HasValue)
            {
                data = data.Where(a => a.OperatingStatus== operatingStatus);
            }
            #endregion

            return data;
        }

        /// <summary>
        /// 冗余字段赋值
        /// </summary>
        /// <param name="input"></param>
        /// <param name="isSearchImage">是否查询图片</param>
        /// <param name="isSearchEventsType">是否查询运动类型</param>
        /// <returns></returns>
        private async Task SiteTypeMap(List<BasVenuesBasicDto> input, bool isSearchImage, bool isSearchEventsType)
        {
            if (input.IsNullOrEmpty() || !input.Any()) return;

            //机构
            var orgIds = input.Select(a => a.CreateOrgId).Distinct().ToList();
            var orgData = await _sysOrgRep.AsQueryable().Where(a => a.IsDelete == false && orgIds.Contains(a.Id)).Select(a => new { a.Id, a.Name }).ToListAsync();

            //运动项目类型
            var venuesEventsTypeList = new List<BasVenuesEventsTypeBasicDto>();
            if (isSearchEventsType)
            {
                var venuesIds = input.Select(a => a.Id).ToList();
                venuesEventsTypeList = _basVenuesEventsTypeRep.AsQueryable()
                    .InnerJoin<BasSportsEventsType>((a, b) => a.SportsEventsTypeCode == b.SportsEventsCode)
                    .Where((a, b) => a.SportsEventsTypeCode != null && a.IsDelete == false && b.IsDelete == false && venuesIds.Contains(a.VenuesId))
                    .Select((a, b) => new BasVenuesEventsTypeBasicDto { Id = a.Id, VenuesId = a.VenuesId, SportsEventsTypeCode = a.SportsEventsTypeCode, SportsEventsTypeTValue = b.SportsEventsName })
                    .ToList();

            }


            //营业状态
            var dictCodeList = new List<string>()
            {
                DictConsts.BAS_OperatingStatus
            };
            var dictData = _sysDictTypeRep.AsQueryable()
                .InnerJoin<SysDictData>((a, b) => a.Id == b.DictTypeId)
                .Where((a, b) => dictCodeList.Contains(a.Code) && a.IsDelete == false)
               .Select((a, b) => new { DictCode = a.Code, DictValueCode = b.Code, DictValue = b.Value })
               .ToList();

            #region 场馆图片 
            var imageData = new List<BasVenuesImageBasicDto>();
            if (isSearchImage)
            {
                var venuesIds = input.Select(a => a.Id).ToList();
                imageData = _basVenuesImageRep.AsQueryable().Where(a => venuesIds.Contains(a.VenuesId)).Select(a => new BasVenuesImageBasicDto { Id = a.Id, Image = a.Image, VenuesId = a.VenuesId }).ToList();
            }
            #endregion

            //营业状态：用全局值
            foreach (var item in input)
            {
                var venuesId = item.Id;

               

                #region 图片

                if (isSearchImage)
                {
                    item.ImageList = new List<BasVenuesImageBasicDto>();
                    item.ImageList = imageData.Where(a => a.VenuesId == venuesId).ToList();
                }

                #endregion

                #region 运动项目类型

                if (isSearchEventsType && !venuesEventsTypeList.IsNullOrEmpty() && venuesEventsTypeList.Any())
                {
                    item.EventsTypeList = venuesEventsTypeList.Where(a => a.VenuesId == venuesId).ToList();
                }
                #endregion 

            }

        }

        /// <summary>
        /// 参数为NULL验证
        /// </summary>
        /// <param name="input"></param>
        private void ParamNull(object input)
        {
            if (input == null) throw Oops.Oh("参数错误:参数为NULL");
        }


        private async Task EditVenuesEventsTypeAndVenuesImage(long venuesId, List<EventsTypeCreateUpdateInputDto> eventsTypeList, List<ImageListCreateUpdateInputDto> imageList)
        {

            #region 运动图片

            var venuesImage = await _basVenuesImageRep.AsQueryable().Where(x => x.VenuesId == venuesId).ToListAsync();

            var delImageList = imageList.Where(x => !venuesImage.Select(y => y.Image).Contains(x.Images)).ToList();
            var addImageList = venuesImage.Where(x => !imageList.Select(x => x.Images).Contains(x.Image)).ToList();


            if (addImageList.Count > 0)
            {
                var addImageData = addImageList.Select(a => new BasVenuesImage { Image = a.Image, VenuesId = venuesId }).ToList();
                await _basVenuesImageRep.AsInsertable(addImageData).ExecuteReturnEntityAsync();
            }
            if (delImageList.Count > 0)
            {
                var delImageData = venuesImage.Where(x => delImageList.Select(x => x.Images).Contains(x.Image)).ToList();
                await _basVenuesImageRep.DeleteAsync(delImageData);
            }

            #endregion

            #region 运动项目类型
            var venuesEventsType = _basVenuesEventsTypeRep.AsQueryable().Where(x => x.VenuesId == venuesId).ToList();

            var addEventsTypeList = eventsTypeList.Where(x => !venuesEventsType.Select(y => y.SportsEventsTypeCode).Contains(x.SportsEventsTypeCode)).ToList();
            var delEventsTypeList = venuesEventsType.Where(x => !eventsTypeList.Select(y => y.SportsEventsTypeCode).Contains(x.SportsEventsTypeCode)).ToList();
            if (addEventsTypeList.Count > 0)
            {
                var addEventsTypeData = addEventsTypeList.Select(a => new BasVenuesEventsType { SportsEventsTypeCode = a.SportsEventsTypeCode, VenuesId = venuesId }).ToList();
                await _basVenuesEventsTypeRep.AsInsertable(addEventsTypeData).ExecuteReturnEntityAsync();
            }
            if (delEventsTypeList.Count > 0)
            {
                var delImageData = venuesEventsType.Where(x => delEventsTypeList.Select(x => x.SportsEventsTypeCode).Contains(x.SportsEventsTypeCode)).ToList();

                await _basVenuesEventsTypeRep.DeleteAsync(delImageData);
            }
            #endregion
        }
        #endregion

    }


}
